/**
 * edurender
 * SoftwareQuake3Model.cpp
 * (c) 2009 J. Brad Byrd
 */

#include "SoftwareQuake3Model.h"
#include "Quake3Model.h"
#include "RenderState.h"
#include "SoftwareRenderer.h"

er::SoftwareQuake3Model *er::SoftwareQuake3Model::Create(
	er::Quake3ModelReader *reader, er::SoftwareRenderer *renderer)
{
	SoftwareQuake3Model *model = new SoftwareQuake3Model(renderer);
	
	if (!model->Initialize(reader))
	{
		delete model;
		model = 0;
	}
	
	return model;
}

void er::SoftwareQuake3Model::Destroy(er::SoftwareQuake3Model *model)
{
	delete model;
}

void er::SoftwareQuake3Model::Draw(const er::RenderState &renderState)
{
	m_renderer->SetPositionPointer(3, sizeof(Vertex), &m_vertices[0].position.x);
	//m_renderer->Draw(PRIMITIVE_POINTS, m_vertices.size(), 0, renderState);
	m_renderer->DrawIndexed(PRIMITIVE_TRIANGLES, 0, static_cast<UInt16>(m_vertices.size()),
		static_cast<UInt16>(m_indices.size()), &m_indices[0], renderState); 
}

er::SoftwareQuake3Model::SoftwareQuake3Model(er::SoftwareRenderer *renderer) :
	m_renderer(renderer)
{
}

er::SoftwareQuake3Model::~SoftwareQuake3Model()
{

}

bool er::SoftwareQuake3Model::Initialize(er::Quake3ModelReader *reader)
{
	for (UInt32 i = 0; i < reader->GetSurfaceCount(); ++i)
	{
		const Quake3ModelReader::Surface *surface = reader->GetSurface(i);
		size_t offset = m_vertices.size();
	
		const Quake3ModelReader::XyzNormal *xyzNormals = surface->GetXyzNormals(0);
	
		for (UInt32 j = 0; j < surface->GetXyzNormalsCount(); ++j)
		{
			const Quake3ModelReader::XyzNormal *xyzNormal = &xyzNormals[j];
			
			Vertex vertex;
			vertex.position.x = xyzNormal->x * Quake3ModelReader::MD3_XYZ_SCALE;
			vertex.position.y = xyzNormal->y * Quake3ModelReader::MD3_XYZ_SCALE;
			vertex.position.z = xyzNormal->z * Quake3ModelReader::MD3_XYZ_SCALE;

			/*
			float lat = ((xyzNormal->normal >> 8) & 255) * (2.0f * 3.1415926f) / 255.0f;
			float lng = (xyzNormal->normal & 255) * (2.0f * 3.1415926f) / 255.0f;

			vertex.normal.x = cosf(lat) * sinf(lng);
			vertex.normal.y = sinf(lat) * sinf(lng);
			vertex.normal.z = cosf(lng);
			
			::D3DXVec3Normalize(&vertex.normal, &vertex.normal);
			*/
			
			m_vertices.push_back(vertex);
		}

		const UInt32 *surfaceIndices = surface->GetIndices();
		
		for (UInt32 j = 0; j < surface->GetIndexCount(); ++j)
		{
			m_indices.push_back(static_cast<UInt16>(surfaceIndices[j] + offset));
		}
	}

	return true;
}
